﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Net.Chirash.Twitter.TweetZone.WindowComponents.Containers;
using Net.Chirash.Twitter.TweetZone.WindowComponents.ViewModels;
using Net.Chirash.Twitter.TwitterClient;
using Net.Chirash.Twitter.TwitterDatabase;

namespace Net.Chirash.Twitter.TweetZone.WindowComponents
{
    /// <summary>
    /// ZonePanel.xaml の相互作用ロジック
    /// </summary>
    [System.Windows.Markup.ContentProperty("ZoneContainerCollection")]
    public partial class ZonePanel : UserControl
    {
        #region Constructors

        public ZonePanel()
        {
            InitializeComponent();
        }

        #endregion

        #region Enumerations

        public enum Types
        {
            Default,
            Analysis,
            Various,
            Empty,
        }

        #endregion

        #region Public Members

        public ZoneContainerCollection ZoneContainerCollection
        {
            get { return this.Resources["ZoneContainerCollectionKey"] as ZoneContainerCollection; }
        }

        public void ChangeZone(Types type)
        {
            ChangeZone(type, App.CurrentApp.User);
        }

        public ZoneControllerViewModel AddContainer(Type ContainerType, ContainerViewModelBase ContainerVM)
        {
            var vm = new ZoneControllerViewModel(ContainerType, ContainerVM);
            ZoneContainerCollection.Add(vm);
            return vm;
        }

        public void ChangeZone(Types type, User user)
        {
            ZoneContainerCollection.Clear();

            switch (type)
            {
                case Types.Default:
                    AddContainer(typeof(TimelineContainer), new RecentStatusContainerViewModel());
                    AddContainer(typeof(TimelineContainer), new TimelineContainerViewModel(TimelineTypes.Home));
                    AddContainer(typeof(TimelineContainer), new TimelineContainerViewModel(TimelineTypes.Mentions));
                    AddContainer(typeof(DirectMessageContainer), new DirectMessageViewModel());
                    AddContainer(typeof(UsersContainer), new UserContainerViewModel(UserListType.Friend, App.CurrentApp.User));
                    break;
                case Types.Analysis:
                    AddContainer(typeof(ChartContainer), new ChartContainerViewModel());
                    AddContainer(typeof(SearchContainer), new SearchContainerViewModel());
                    break;
                case Types.Various:
                    AddContainer(typeof(TimelineContainer), new TimelineContainerViewModel(TimelineTypes.Home));
                    AddContainer(typeof(UsersContainer), new UserContainerViewModel(UserListType.Friend, App.CurrentApp.User));
                    AddContainer(typeof(ChartContainer), new ChartContainerViewModel());
                    AddContainer(typeof(SearchContainer), new SearchContainerViewModel());
                    break;
                case Types.Empty:
                    break;
            }

            //Refresh();
        }

        public void Refresh()
        {
            foreach (ZoneControllerViewModel vm in ZoneContainerCollection)
            {
                vm.Composer.ContainerViewModel.Refresh();
            }
        }

        public void RefreshAsync(Action<ContainerViewModelBase> completed = null, Action allCompleted = null)
        {
            int commandedCount = 0, completedCount = 0;

            foreach (ZoneControllerViewModel vmSource in ZoneContainerCollection)
            {
                var operation = Dispatcher.BeginInvoke(new Action<ZoneControllerViewModel>((vm) =>
                {
                    vm.Composer.ContainerViewModel.RefreshAsync
                        (new Action<ContainerViewModelBase>((arg) =>
                            {
                                if (completed != null && vm.Composer != null && vm.Composer.IsViewCreated)
                                {
                                    vm.Composer.AssociatedDispatcher.BeginInvoke(completed, arg);
                                }

                                completedCount++;
                            }
                            ));
                }), vmSource);

                commandedCount++;
            }

            if (allCompleted != null)
            {
                var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
                Task.Factory.StartNew(new Action(() =>
                    {
                        while (commandedCount != completedCount)
                        {
                            System.Threading.Thread.Sleep(100);
                        }
                    }))
                    .ContinueWith(new Action<Task>((task) =>
                        {
                            allCompleted();
                        }
                    ), uiScheduler);
            }
        }

        #endregion

        #region DragDropEvents

        private Point startPos;
        private void rootControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            startPos = e.GetPosition(null);
        }

        private void rootControl_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed
                && this.ContainerBox.SelectedItem != null
                && !(e.OriginalSource is System.Windows.Controls.Primitives.Thumb))//ScrollBarつかむとThumbから発生する(場当たり的･･･)
            {
                var curPos = e.GetPosition(null);
                var diff = curPos - startPos;
                if (Math.Abs(diff.X) >= SystemParameters.MinimumVerticalDragDistance
                    || Math.Abs(diff.Y) >= SystemParameters.MinimumHorizontalDragDistance)
                {
                    var selected = this.ContainerBox.SelectedItem as ZoneControllerViewModel;
                    var data = new DataObject(typeof(ZoneControllerViewModel), selected);
                    var result = DragDrop.DoDragDrop(this, data, DragDropEffects.Move);
                }
            }
        }

        #endregion



    }

}
